home *** CD-ROM | disk | FTP | other *** search
/ CU Amiga Super CD-ROM 24 / CU Amiga Magazine's Super CD-ROM 24 (1998)(EMAP Images)(GB)(Track 1 of 2)[!][issue 1998-07].iso / CUCD / Utilities / vim-5.1 / src / os_amiga.c < prev    next >
Encoding:
C/C++ Source or Header  |  1998-03-29  |  30.0 KB  |  1,429 lines

  1. /* vi:set ts=8 sts=4 sw=4:
  2.  *
  3.  * VIM - Vi IMproved    by Bram Moolenaar
  4.  *
  5.  * Do ":help uganda"  in Vim to read copying and usage conditions.
  6.  * Do ":help credits" in Vim to see a list of people who contributed.
  7.  */
  8.  
  9. /*
  10.  * os_amiga.c
  11.  *
  12.  * Amiga system-dependent routines.
  13.  */
  14.  
  15. #include "vim.h"
  16.  
  17. #ifdef HAVE_FCNTL_H
  18. # include <fcntl.h>
  19. #endif
  20.  
  21. #undef TRUE        /* will be redefined by exec/types.h */
  22. #undef FALSE
  23.  
  24. #ifndef LATTICE
  25. # include <exec/types.h>
  26. # include <exec/exec.h>
  27. # include <libraries/dos.h>
  28. # include <libraries/dosextens.h>
  29. # include <intuition/intuition.h>
  30. #else
  31. # include <proto/dos.h>
  32. # include <libraries/dosextens.h>
  33. # include <proto/intuition.h>
  34. # include <proto/exec.h>
  35. #endif
  36.  
  37. #include <exec/memory.h>
  38.  
  39. #include <dos/dostags.h>        /* for 2.0 functions */
  40. #include <dos/dosasl.h>
  41.  
  42. #if defined(LATTICE) && !defined(SASC) && !defined(NO_ARP)
  43. # include <libraries/arp_pragmas.h>
  44. #endif
  45.  
  46. /*
  47.  * At this point TRUE and FALSE are defined as 1L and 0L, but we want 1 and 0.
  48.  */
  49. #undef    TRUE
  50. #define TRUE (1)
  51. #undef    FALSE
  52. #define FALSE (0)
  53.  
  54. #ifndef AZTEC_C
  55. static long dos_packet __ARGS((struct MsgPort *, long, long));
  56. #endif
  57. static int lock2name __ARGS((BPTR lock, char_u *buf, long   len));
  58. static void out_num __ARGS((long n));
  59. static struct FileInfoBlock *get_fib __ARGS((char_u *));
  60. static int sortcmp __ARGS((char **a, char **b));
  61.  
  62. static BPTR        raw_in = (BPTR)NULL;
  63. static BPTR        raw_out = (BPTR)NULL;
  64. static int        close_win = FALSE;  /* set if Vim opened the window */
  65.  
  66. struct IntuitionBase    *IntuitionBase = NULL;
  67. #ifndef NO_ARP
  68. struct ArpBase        *ArpBase = NULL;
  69. #endif
  70.  
  71. static struct Window    *wb_window;
  72. static char_u        *oldwindowtitle = NULL;
  73.  
  74. #ifndef NO_ARP
  75. int            dos2 = FALSE;        /* Amiga DOS 2.0x or higher */
  76. #endif
  77. int            size_set = FALSE;   /* set to TRUE if window size was set */
  78.  
  79.     void
  80. win_resize_on()
  81. {
  82.     OUT_STR_NF("\033[12{");
  83. }
  84.  
  85.     void
  86. win_resize_off()
  87. {
  88.     OUT_STR_NF("\033[12}");
  89. }
  90.  
  91.     void
  92. mch_write(p, len)
  93.     char_u  *p;
  94.     int        len;
  95. {
  96.     Write(raw_out, (char *)p, (long)len);
  97. }
  98.  
  99. /*
  100.  * mch_inchar(): low level input funcion.
  101.  * Get a characters from the keyboard.
  102.  * If time == 0 do not wait for characters.
  103.  * If time == n wait a short time for characters.
  104.  * If time == -1 wait forever for characters.
  105.  *
  106.  * Return number of characters read.
  107.  */
  108.     int
  109. mch_inchar(buf, maxlen, time)
  110.     char_u  *buf;
  111.     int        maxlen;
  112.     long    time;        /* milli seconds */
  113. {
  114.     int        len;
  115.     long    utime;
  116.  
  117.     if (time >= 0)
  118.     {
  119.     if (time == 0)
  120.         utime = 100L;        /* time = 0 causes problems in DOS 1.2 */
  121.     else
  122.         utime = time * 1000L;   /* convert from milli to micro secs */
  123.     if (WaitForChar(raw_in, utime) == 0)    /* no character available */
  124.         return 0;
  125.     }
  126.     else    /* time == -1 */
  127.     {
  128.     /*
  129.      * If there is no character available within 2 seconds (default)
  130.      * write the autoscript file to disk
  131.      */
  132.     if (WaitForChar(raw_in, p_ut * 1000L) == 0)
  133.         updatescript(0);
  134.     }
  135.  
  136.     for (;;)        /* repeat until we got a character */
  137.     {
  138.     len = Read(raw_in, (char *)buf, (long)maxlen);
  139.     if (len > 0)
  140.         return len;
  141.     }
  142. }
  143.  
  144. /*
  145.  * return non-zero if a character is available
  146.  */
  147.     int
  148. mch_char_avail()
  149. {
  150.     return (WaitForChar(raw_in, 100L) != 0);
  151. }
  152.  
  153.     long_u
  154. mch_avail_mem(special)
  155.     int        special;
  156. {
  157.     return (long_u)AvailMem(special ? (long)MEMF_CHIP : (long)MEMF_ANY);
  158. }
  159.  
  160.     void
  161. mch_delay(msec, ignoreinput)
  162.     long    msec;
  163.     int        ignoreinput;
  164. {
  165. #ifndef LATTICE        /* SAS declares void Delay(UNLONG) */
  166.     void        Delay __ARGS((long));
  167. #endif
  168.  
  169.     if (msec > 0)
  170.     {
  171.     if (ignoreinput)
  172.         Delay(msec / 20L);        /* Delay works with 20 msec intervals */
  173.     else
  174.         WaitForChar(raw_in, msec * 1000L);
  175.     }
  176. }
  177.  
  178. /*
  179.  * We have no job control, fake it by starting a new shell.
  180.  */
  181.     void
  182. mch_suspend()
  183. {
  184.     suspend_shell();
  185. }
  186.  
  187. #define DOS_LIBRARY    ((UBYTE *) "dos.library")
  188.  
  189.     void
  190. mch_windinit()
  191. {
  192.     static char        intlibname[] = "intuition.library";
  193.  
  194. #ifdef AZTEC_C
  195.     Enable_Abort = 0;        /* disallow vim to be aborted */
  196. #endif
  197.     Columns = 80;
  198.     Rows = 24;
  199.  
  200.     /*
  201.      * Set input and output channels, unless we have opened our own window
  202.      */
  203.     if (raw_in == (BPTR)NULL)
  204.     {
  205.     raw_in = Input();
  206.     raw_out = Output();
  207.     /*
  208.      * If Input() is not interactive, then Output() will be (because of
  209.      * check in mch_check_win()).  Used for "Vim -".
  210.      * Also check the other way around, for "Vim -h | more".
  211.      */
  212.     if (!IsInteractive(raw_in))
  213.         raw_in = raw_out;
  214.     else if (!IsInteractive(raw_out))
  215.         raw_out = raw_in;
  216.     }
  217.  
  218.     out_flush();
  219.  
  220.     wb_window = NULL;
  221.     if ((IntuitionBase = (struct IntuitionBase *)
  222.                 OpenLibrary((UBYTE *)intlibname, 0L)) == NULL)
  223.     {
  224.     mch_errmsg("cannot open ");
  225.     mch_errmsg(intlibname);
  226.     mch_errmsg("!?\n");
  227.     mch_windexit(3);
  228.     }
  229. }
  230.  
  231. #include <workbench/startup.h>
  232.  
  233. /*
  234.  * Check_win checks whether we have an interactive window.
  235.  * If not, a new window is opened with the newcli command.
  236.  * If we would open a window ourselves, the :sh and :! commands would not
  237.  * work properly (Why? probably because we are then running in a background
  238.  * CLI). This also is the best way to assure proper working in a next
  239.  * Workbench release.
  240.  *
  241.  * For the -f option (foreground mode) we open our own window and disable :sh.
  242.  * Otherwise the calling program would never know when editing is finished.
  243.  */
  244. #define BUF2SIZE 320        /* length of buffer for argument with complete path */
  245.  
  246.     int
  247. mch_check_win(argc, argv)
  248.     int argc;
  249.     char **argv;
  250. {
  251.     int            i;
  252.     BPTR        nilfh, fh;
  253.     char_u        buf1[20];
  254.     char_u        buf2[BUF2SIZE];
  255.     static char_u   *(constrings[3]) = {(char_u *)"con:0/0/662/210/",
  256.                     (char_u *)"con:0/0/640/200/",
  257.                     (char_u *)"con:0/0/320/200/"};
  258.     static char_u   winerr[] = "VIM: Can't open window!\n";
  259.     struct WBArg    *argp;
  260.     int            ac;
  261.     char        *av;
  262.     char_u        *device = NULL;
  263.     int            exitval = 4;
  264.     struct Library  *DosBase;
  265.     int            usewin = FALSE;
  266.  
  267. /*
  268.  * check if we are running under DOS 2.0x or higher
  269.  */
  270.     if (DosBase = OpenLibrary(DOS_LIBRARY, 37L))
  271.     {
  272.     CloseLibrary(DosBase);
  273. #ifndef NO_ARP
  274.     dos2 = TRUE;
  275. #endif
  276.     }
  277.     else        /* without arp functions we NEED 2.0 */
  278.     {
  279. #ifdef NO_ARP
  280.     mch_errmsg("Need Amigados version 2.04 or later\n");
  281.     exit(3);
  282. #else
  283.             /* need arp functions for dos 1.x */
  284.     if (!(ArpBase = (struct ArpBase *) OpenLibrary((UBYTE *)ArpName, ArpVersion)))
  285.     {
  286.         fprintf(stderr, "Need %s version %ld\n", ArpName, ArpVersion);
  287.         exit(3);
  288.     }
  289. #endif
  290.     }
  291.  
  292. /*
  293.  * scan argv[] for the "-f" and "-d" arguments
  294.  */
  295.     for (i = 1; i < argc; ++i)
  296.     if (argv[i][0] == '-')
  297.     {
  298.         switch (argv[i][1])
  299.         {
  300.         case 'f':
  301.         usewin = TRUE;
  302.         break;
  303.  
  304.         case 'd':
  305.         if (i < argc - 1)
  306.             device = (char_u *)argv[i + 1];
  307.         break;
  308.         }
  309.     }
  310.  
  311. /*
  312.  * If we were not started from workbench, do not have a '-d' argument and
  313.  * we have been started with an interactive window, use that window.
  314.  */
  315.     if (argc != 0 && device == NULL &&
  316.               (IsInteractive(Input()) || IsInteractive(Output())))
  317.     return OK;
  318.  
  319. /*
  320.  * When given the "-f" argument, we open our own window. We can't use the
  321.  * newcli trick below, because the calling program (mail, rn, etc.) would not
  322.  * know when we are finished.
  323.  */
  324.     if (usewin)
  325.     {
  326.     /*
  327.      * Try to open a window. First try the specified device.
  328.      * Then try a 24 line 80 column window.
  329.      * If that fails, try two smaller ones.
  330.      */
  331.     for (i = -1; i < 3; ++i)
  332.     {
  333.         if (i >= 0)
  334.         device = constrings[i];
  335.         if (device && (raw_in = Open((UBYTE *)device,
  336.                        (long)MODE_NEWFILE)) != (BPTR)NULL)
  337.         break;
  338.     }
  339.     if (raw_in == (BPTR)NULL)    /* all three failed */
  340.     {
  341.         mch_errmsg((char *)winerr);
  342.         goto exit;
  343.     }
  344.     raw_out = raw_in;
  345.     close_win = TRUE;
  346.     return OK;
  347.     }
  348.  
  349.     if ((nilfh = Open((UBYTE *)"NIL:", (long)MODE_NEWFILE)) == (BPTR)NULL)
  350.     {
  351.     mch_errmsg("Cannot open NIL:\n");
  352.     goto exit;
  353.     }
  354.  
  355.     /*
  356.      * Make a unique name for the temp file (which we will not delete!).
  357.      * Use a pointer on the stack (nobody else will be using it).
  358.      */
  359.     sprintf((char *)buf1, "t:nc%ld", (char *)buf1);
  360.     if ((fh = Open((UBYTE *)buf1, (long)MODE_NEWFILE)) == (BPTR)NULL)
  361.     {
  362.     mch_errmsg("Cannot create ");
  363.     mch_errmsg((char *)buf1);
  364.     mch_errmsg("\n");
  365.     goto exit;
  366.     }
  367.     /*
  368.      * Write the command into the file, put quotes around the arguments that
  369.      * have a space in them.
  370.      */
  371.     if (argc == 0)    /* run from workbench */
  372.     ac = ((struct WBStartup *)argv)->sm_NumArgs;
  373.     else
  374.     ac = argc;
  375.     for (i = 0; i < ac; ++i)
  376.     {
  377.     if (argc == 0)
  378.     {
  379.         *buf2 = NUL;
  380.         argp = &(((struct WBStartup *)argv)->sm_ArgList[i]);
  381.         if (argp->wa_Lock)
  382.         (void)lock2name(argp->wa_Lock, buf2, (long)(BUF2SIZE - 1));
  383. #ifndef NO_ARP
  384.         if (dos2)        /* use 2.0 function */
  385. #endif
  386.         AddPart((UBYTE *)buf2, (UBYTE *)argp->wa_Name, (long)(BUF2SIZE - 1));
  387. #ifndef NO_ARP
  388.         else        /* use arp function */
  389.         TackOn((char *)buf2, argp->wa_Name);
  390. #endif
  391.         av = (char *)buf2;
  392.     }
  393.     else
  394.         av = argv[i];
  395.  
  396.     if (av[0] == '-' && av[1] == 'd')    /* skip '-d' option */
  397.     {
  398.         ++i;
  399.         continue;
  400.     }
  401.     if (vim_strchr((char_u *)av, ' '))
  402.         Write(fh, "\"", 1L);
  403.     Write(fh, av, (long)strlen(av));
  404.     if (vim_strchr((char_u *)av, ' '))
  405.         Write(fh, "\"", 1L);
  406.     Write(fh, " ", 1L);
  407.     }
  408.     Write(fh, "\nendcli\n", 8L);
  409.     Close(fh);
  410.  
  411. /*
  412.  * Try to open a new cli in a window. If '-d' argument was given try to open
  413.  * the specified device. Then try a 24 line 80 column window.
  414.  * If that fails, try two smaller ones.
  415.  */
  416.     for (i = -1; i < 3; ++i)
  417.     {
  418.     if (i >= 0)
  419.         device = constrings[i];
  420.     else if (device == NULL)
  421.         continue;
  422.     sprintf((char *)buf2, "newcli <nil: >nil: %s from %s", (char *)device, (char *)buf1);
  423. #ifndef NO_ARP
  424.     if (dos2)
  425.     {
  426. #endif
  427.         if (!SystemTags((UBYTE *)buf2, SYS_UserShell, TRUE, TAG_DONE))
  428.         break;
  429. #ifndef NO_ARP
  430.     }
  431.     else
  432.     {
  433.         if (Execute((UBYTE *)buf2, nilfh, nilfh))
  434.         break;
  435.     }
  436. #endif
  437.     }
  438.     if (i == 3)        /* all three failed */
  439.     {
  440.     DeleteFile((UBYTE *)buf1);
  441.     mch_errmsg((char *)winerr);
  442.     goto exit;
  443.     }
  444.     exitval = 0;    /* The Execute succeeded: exit this program */
  445.  
  446. exit:
  447. #ifndef NO_ARP
  448.     if (ArpBase)
  449.     CloseLibrary((struct Library *) ArpBase);
  450. #endif
  451.     exit(exitval);
  452.     /* NOTREACHED */
  453.     return FAIL;
  454. }
  455.  
  456. /*
  457.  * Return TRUE if the input comes from a terminal, FALSE otherwise.
  458.  * We fake there is a window, because we can always open one!
  459.  */
  460.     int
  461. mch_input_isatty()
  462. {
  463.     return TRUE;
  464. }
  465.  
  466. /*
  467.  * fname_case(): Set the case of the file name, if it already exists.
  468.  *         This will cause the file name to remain exactly the same.
  469.  */
  470.     void
  471. fname_case(name)
  472.     char_u  *name;
  473. {
  474.     struct FileInfoBlock    *fib;
  475.     size_t            len;
  476.  
  477.     fib = get_fib(name);
  478.     if (fib != NULL)
  479.     {
  480.     len = STRLEN(name);
  481.     if (len == strlen(fib->fib_FileName))    /* safety check */
  482.         vim_memmove(name, fib->fib_FileName, len);
  483.     vim_free(fib);
  484.     }
  485. }
  486.  
  487. /*
  488.  * Get the FileInfoBlock for file "fname"
  489.  * The returned structure has to be free()d.
  490.  * Returns NULL on error.
  491.  */
  492.     static struct FileInfoBlock *
  493. get_fib(fname)
  494.     char_u *fname;
  495. {
  496.     BPTR            flock;
  497.     struct FileInfoBlock    *fib;
  498.  
  499.     if (fname == NULL)        /* safety check */
  500.     return NULL;
  501.     fib = (struct FileInfoBlock *)malloc(sizeof(struct FileInfoBlock));
  502.     if (fib != NULL)
  503.     {
  504.     flock = Lock((UBYTE *)fname, (long)ACCESS_READ);
  505.     if (flock == (BPTR)NULL || !Examine(flock, fib))
  506.     {
  507.         vim_free(fib);  /* in case of an error the memory is freed here */
  508.         fib = NULL;
  509.     }
  510.     if (flock)
  511.         UnLock(flock);
  512.     }
  513.     return fib;
  514. }
  515.  
  516. /*
  517.  * set the title of our window
  518.  * icon name is not set
  519.  */
  520.     void
  521. mch_settitle(title, icon)
  522.     char_u  *title;
  523.     char_u  *icon;
  524. {
  525.     if (wb_window != NULL && title != NULL)
  526.     SetWindowTitles(wb_window, (UBYTE *)title, (UBYTE *)-1L);
  527. }
  528.  
  529. /*
  530.  * Restore the window/icon title.
  531.  * which is one of:
  532.  *  1  Just restore title
  533.  *  2  Just restore icon (which we don't have)
  534.  *  3  Restore title and icon (which we don't have)
  535.  */
  536.     void
  537. mch_restore_title(which)
  538.     int which;
  539. {
  540.     if (which & 1)
  541.     mch_settitle(oldwindowtitle, NULL);
  542. }
  543.  
  544.     int
  545. mch_can_restore_title()
  546. {
  547.     return (wb_window != NULL);
  548. }
  549.  
  550.     int
  551. mch_can_restore_icon()
  552. {
  553.     return FALSE;
  554. }
  555.  
  556. /*
  557.  * Insert user name in s[len].
  558.  */
  559.     int
  560. mch_get_user_name(s, len)
  561.     char_u  *s;
  562.     int        len;
  563. {
  564.     *s = NUL;
  565.     return FAIL;
  566. }
  567.  
  568. /*
  569.  * Insert host name is s[len].
  570.  */
  571.     void
  572. mch_get_host_name(s, len)
  573.     char_u  *s;
  574.     int        len;
  575. {
  576.     STRNCPY(s, "Amiga", len);
  577. }
  578.  
  579. /*
  580.  * return process ID
  581.  */
  582.     long
  583. mch_get_pid()
  584. {
  585.     return (long)0;
  586. }
  587.  
  588. /*
  589.  * Get name of current directory into buffer 'buf' of length 'len' bytes.
  590.  * Return OK for success, FAIL for failure.
  591.  */
  592.     int
  593. mch_dirname(buf, len)
  594.     char_u    *buf;
  595.     int        len;
  596. {
  597.     return mch_FullName((char_u *)"", buf, len, FALSE);
  598. }
  599.  
  600. /*
  601.  * get absolute file name into buffer 'buf' of length 'len' bytes
  602.  *
  603.  * return FAIL for failure, OK otherwise
  604.  */
  605.     int
  606. mch_FullName(fname, buf, len, force)
  607.     char_u    *fname, *buf;
  608.     int        len;
  609.     int        force;
  610. {
  611.     BPTR    l;
  612.     int        retval = FAIL;
  613.     int        i;
  614.  
  615.     *buf = NUL;
  616.     if (fname == NULL)    /* always fail */
  617.     return FAIL;
  618.  
  619.     if ((l = Lock((UBYTE *)fname, (long)ACCESS_READ)) != (BPTR)0)/* lock the file */
  620.     {
  621.     retval = lock2name(l, buf, (long)len);
  622.     UnLock(l);
  623.     }
  624.     else if (force || !mch_isFullName(fname))        /* not a full path yet */
  625.     {
  626.     /*
  627.      * If cannot lock the file, try to lock the current directory and then
  628.      * concatenate the file name.  Works when file doesn't exist yet.
  629.      */
  630.     if ((l = Lock((UBYTE *)"", (long)ACCESS_READ)) != (BPTR)NULL) /* lock current dir */
  631.     {
  632.         retval = lock2name(l, buf, (long)len);
  633.         UnLock(l);
  634.         if (retval == OK)
  635.         {
  636.         i = STRLEN(buf);
  637.         if (i < len - 1 && (i == 0 || buf[i - 1] != ':'))
  638.             buf[i++] = '/';
  639.         STRNCPY(buf + i, fname, (len - i)); /* concatenate the fname */
  640.         }
  641.     }
  642.     }
  643.     if (retval == FAIL || *buf == 0 || *buf == ':')
  644.     STRCPY(buf, fname); /* something failed; use the file name */
  645.     return retval;
  646. }
  647.  
  648. /*
  649.  * return TRUE is fname is an absolute path name
  650.  */
  651.     int
  652. mch_isFullName(fname)
  653.     char_u    *fname;
  654. {
  655.     return (vim_strchr(fname, ':') != NULL);
  656. }
  657.  
  658. /*
  659.  * Get the full file name from a lock. Use 2.0 function if possible, because
  660.  * the arp function has more restrictions on the path length.
  661.  *
  662.  * return FAIL for failure, OK otherwise
  663.  */
  664.     static int
  665. lock2name(lock, buf, len)
  666.     BPTR    lock;
  667.     char_u  *buf;
  668.     long    len;
  669. {
  670. #ifndef NO_ARP
  671.     if (dos2)            /* use 2.0 function */
  672. #endif
  673.     return ((int)NameFromLock(lock, (UBYTE *)buf, len) ? OK : FAIL);
  674. #ifndef NO_ARP
  675.     else        /* use arp function */
  676.     return ((int)PathName(lock, (char *)buf, (long)(len/32)) ? OK : FAIL);
  677. #endif
  678. }
  679.  
  680. /*
  681.  * get file permissions for 'name'
  682.  */
  683.     long
  684. mch_getperm(name)
  685.     char_u    *name;
  686. {
  687.     struct FileInfoBlock    *fib;
  688.     long            retval = -1;
  689.  
  690.     fib = get_fib(name);
  691.     if (fib != NULL)
  692.     {
  693.     retval = fib->fib_Protection;
  694.     vim_free(fib);
  695.     }
  696.     return retval;
  697. }
  698.  
  699. /*
  700.  * set file permission for 'name' to 'perm'
  701.  *
  702.  * return FAIL for failure, OK otherwise
  703.  */
  704.     int
  705. mch_setperm(name, perm)
  706.     char_u    *name;
  707.     long    perm;
  708. {
  709.     perm &= ~FIBF_ARCHIVE;        /* reset archived bit */
  710.     return (SetProtection((UBYTE *)name, (long)perm) ? OK : FAIL);
  711. }
  712.  
  713. /*
  714.  * Set hidden flag for "name".
  715.  */
  716.     void
  717. mch_hide(name)
  718.     char_u    *name;
  719. {
  720.     /* can't hide a file */
  721. }
  722.  
  723. /*
  724.  * return FALSE if "name" is not a directory
  725.  * return TRUE if "name" is a directory.
  726.  * return FALSE for error.
  727.  */
  728.     int
  729. mch_isdir(name)
  730.     char_u    *name;
  731. {
  732.     struct FileInfoBlock    *fib;
  733.     int                retval = FALSE;
  734.  
  735.     fib = get_fib(name);
  736.     if (fib != NULL)
  737.     {
  738.     retval = ((fib->fib_DirEntryType >= 0) ? TRUE : FALSE);
  739.     vim_free(fib);
  740.     }
  741.     return retval;
  742. }
  743.  
  744. /*
  745.  * Careful: mch_windexit() may be called before mch_windinit()!
  746.  */
  747.     void
  748. mch_windexit(r)
  749.     int            r;
  750. {
  751.     if (raw_in)                /* put terminal in 'normal' mode */
  752.     {
  753.     settmode(TMODE_COOK);
  754.     stoptermcap();
  755.     }
  756.     out_char('\n');
  757.     if (raw_out)
  758.     {
  759.     if (term_console)
  760.     {
  761.         win_resize_off();        /* window resize events de-activated */
  762.         if (size_set)
  763.         OUT_STR("\233t\233u");    /* reset window size (CSI t CSI u) */
  764.     }
  765.     out_flush();
  766.     }
  767.  
  768.     mch_restore_title(3);        /* restore window title */
  769.  
  770.     ml_close_all(TRUE);            /* remove all memfiles */
  771.  
  772. #ifndef NO_ARP
  773.     if (ArpBase)
  774.     CloseLibrary((struct Library *) ArpBase);
  775. #endif
  776.     if (close_win)
  777.     Close(raw_in);
  778.     if (r)
  779.     printf("Vim exiting with %d\n", r); /* somehow this makes :cq work!? */
  780.     exit(r);
  781. }
  782.  
  783. /*
  784.  * This is a routine for setting a given stream to raw or cooked mode on the
  785.  * Amiga . This is useful when you are using Lattice C to produce programs
  786.  * that want to read single characters with the "getch()" or "fgetc" call.
  787.  *
  788.  * Written : 18-Jun-87 By Chuck McManis.
  789.  */
  790.  
  791. #define MP(xx)    ((struct MsgPort *)((struct FileHandle *) (BADDR(xx)))->fh_Type)
  792.  
  793. /*
  794.  * Function mch_settmode() - Convert the specified file pointer to 'raw' or
  795.  * 'cooked' mode. This only works on TTY's.
  796.  *
  797.  * Raw: keeps DOS from translating keys for you, also (BIG WIN) it means
  798.  *    getch() will return immediately rather than wait for a return. You
  799.  *    lose editing features though.
  800.  *
  801.  * Cooked: This function returns the designate file pointer to it's normal,
  802.  *    wait for a <CR> mode. This is exactly like raw() except that
  803.  *    it sends a 0 to the console to make it back into a CON: from a RAW:
  804.  */
  805.     void
  806. mch_settmode(tmode)
  807.     int        tmode;
  808. {
  809.     if (dos_packet(MP(raw_in), (long)ACTION_SCREEN_MODE,
  810.                       tmode == TMODE_RAW ? -1L : 0L) == 0)
  811.     mch_errmsg("cannot change console mode ?!\n");
  812. }
  813.  
  814. /*
  815.  * set screen mode, always fails.
  816.  */
  817.     int
  818. mch_screenmode(arg)
  819.     char_u   *arg;
  820. {
  821.     EMSG("Screen mode setting not supported");
  822.     return FAIL;
  823. }
  824.  
  825. /*
  826.  * Code for this routine came from the following :
  827.  *
  828.  * ConPackets.c -  C. Scheppner, A. Finkel, P. Lindsay    CBM
  829.  *   DOS packet example
  830.  *   Requires 1.2
  831.  *
  832.  * Found on Fish Disk 56.
  833.  *
  834.  * Heavely modified by mool.
  835.  */
  836.  
  837. #include <devices/conunit.h>
  838.  
  839. /*
  840.  * try to get the real window size
  841.  * return FAIL for failure, OK otherwise
  842.  */
  843.     int
  844. mch_get_winsize()
  845. {
  846.     struct ConUnit  *conUnit;
  847.     char        id_a[sizeof(struct InfoData) + 3];
  848.     struct InfoData *id;
  849.  
  850.     if (!term_console)    /* not an amiga window */
  851.     return FAIL;
  852.  
  853.     /* insure longword alignment */
  854.     id = (struct InfoData *)(((long)id_a + 3L) & ~3L);
  855.  
  856.     /*
  857.      * Should make console aware of real window size, not the one we set.
  858.      * Unfortunately, under DOS 2.0x this redraws the window and it
  859.      * is rarely needed, so we skip it now, unless we changed the size.
  860.      */
  861.     if (size_set)
  862.     OUT_STR("\233t\233u");    /* CSI t CSI u */
  863.     out_flush();
  864.  
  865.     if (dos_packet(MP(raw_out), (long)ACTION_DISK_INFO, ((ULONG) id) >> 2) == 0
  866.         || (wb_window = (struct Window *)id->id_VolumeNode) == NULL)
  867.     {
  868.     /* it's not an amiga window, maybe aux device */
  869.     /* terminal type should be set */
  870.     term_console = FALSE;
  871.     return FAIL;
  872.     }
  873.     if (oldwindowtitle == NULL)
  874.     oldwindowtitle = (char_u *)wb_window->Title;
  875.     if (id->id_InUse == (BPTR)NULL)
  876.     {
  877.     mch_errmsg("mch_get_winsize: not a console??\n");
  878.     return FAIL;
  879.     }
  880.     conUnit = (struct ConUnit *) ((struct IOStdReq *) id->id_InUse)->io_Unit;
  881.  
  882.     /* get window size */
  883.     Rows = conUnit->cu_YMax + 1;
  884.     Columns = conUnit->cu_XMax + 1;
  885.     if (Rows < 0 || Rows > 200)        /* cannot be an amiga window */
  886.     {
  887.     Columns = 80;
  888.     Rows = 24;
  889.     term_console = FALSE;
  890.     return FAIL;
  891.     }
  892.     check_winsize();
  893.  
  894.     return OK;
  895. }
  896.  
  897. /*
  898.  * try to set the real window size
  899.  */
  900.     void
  901. mch_set_winsize()
  902. {
  903.     if (term_console)
  904.     {
  905.     size_set = TRUE;
  906.     out_char(CSI);
  907.     out_num((long)Rows);
  908.     out_char('t');
  909.     out_char(CSI);
  910.     out_num((long)Columns);
  911.     out_char('u');
  912.     out_flush();
  913.     }
  914. }
  915.  
  916. /*
  917.  * out_num - output a (big) number fast
  918.  */
  919.     static void
  920. out_num(n)
  921.     long    n;
  922. {
  923.     OUT_STR_NF(tltoa((unsigned long)n));
  924. }
  925.  
  926. #ifndef AZTEC_C
  927. /*
  928.  * Sendpacket.c
  929.  *
  930.  * An invaluable addition to your Amiga.lib file. This code sends a packet to
  931.  * the given message port. This makes working around DOS lots easier.
  932.  *
  933.  * Note, I didn't write this, those wonderful folks at CBM did. I do suggest
  934.  * however that you may wish to add it to Amiga.Lib, to do so, compile it and
  935.  * say 'oml lib:amiga.lib -r sendpacket.o'
  936.  */
  937.  
  938. /* #include <proto/exec.h> */
  939. /* #include <proto/dos.h> */
  940. #include <exec/memory.h>
  941.  
  942. /*
  943.  * Function - dos_packet written by Phil Lindsay, Carolyn Scheppner, and Andy
  944.  * Finkel. This function will send a packet of the given type to the Message
  945.  * Port supplied.
  946.  */
  947.  
  948.     static long
  949. dos_packet(pid, action, arg)
  950.     struct MsgPort *pid;    /* process indentifier ... (handlers message port) */
  951.     long        action, /* packet type ... (what you want handler to do)   */
  952.             arg;    /* single argument */
  953. {
  954. # ifndef NO_ARP
  955.     struct MsgPort        *replyport;
  956.     struct StandardPacket   *packet;
  957.     long            res1;
  958.  
  959.     if (dos2)
  960. # endif
  961.     return DoPkt(pid, action, arg, 0L, 0L, 0L, 0L);    /* use 2.0 function */
  962. # ifndef NO_ARP
  963.  
  964.     replyport = (struct MsgPort *) CreatePort(NULL, 0);    /* use arp function */
  965.     if (!replyport)
  966.     return (0);
  967.  
  968.     /* Allocate space for a packet, make it public and clear it */
  969.     packet = (struct StandardPacket *)
  970.     AllocMem((long) sizeof(struct StandardPacket), MEMF_PUBLIC | MEMF_CLEAR);
  971.     if (!packet) {
  972.     DeletePort(replyport);
  973.     return (0);
  974.     }
  975.     packet->sp_Msg.mn_Node.ln_Name = (char *) &(packet->sp_Pkt);
  976.     packet->sp_Pkt.dp_Link = &(packet->sp_Msg);
  977.     packet->sp_Pkt.dp_Port = replyport;
  978.     packet->sp_Pkt.dp_Type = action;
  979.     packet->sp_Pkt.dp_Arg1 = arg;
  980.  
  981.     PutMsg(pid, (struct Message *)packet);    /* send packet */
  982.  
  983.     WaitPort(replyport);
  984.     GetMsg(replyport);
  985.  
  986.     res1 = packet->sp_Pkt.dp_Res1;
  987.  
  988.     FreeMem(packet, (long) sizeof(struct StandardPacket));
  989.     DeletePort(replyport);
  990.  
  991.     return (res1);
  992. # endif
  993. }
  994. #endif
  995.  
  996. /*
  997.  * call shell, return FAIL for failure, OK otherwise
  998.  */
  999.     int
  1000. mch_call_shell(cmd, options)
  1001.     char_u  *cmd;
  1002.     int        options;        /* SHELL_FILTER if called by do_filter() */
  1003.                 /* SHELL_COOKED if term needs cooked mode */
  1004. {
  1005.     BPTR    mydir;
  1006.     int        x;
  1007. #ifdef AZTEC_C
  1008.     int        use_execute;
  1009.     char_u  *shellcmd = NULL;
  1010.     char_u  *shellarg;
  1011. #endif
  1012.     int    retval = OK;
  1013.  
  1014.     if (close_win)
  1015.     {
  1016.     /* if Vim opened a window: Executing a shell may cause crashes */
  1017.     EMSG("Cannot execute shell with -f option");
  1018.     return FAIL;
  1019.     }
  1020.  
  1021.     if (term_console)
  1022.     win_resize_off();        /* window resize events de-activated */
  1023.     out_flush();
  1024.  
  1025.     if (options & SHELL_COOKED)
  1026.     settmode(TMODE_COOK);        /* set to normal mode */
  1027.     mydir = Lock((UBYTE *)"", (long)ACCESS_READ);   /* remember current directory */
  1028.  
  1029. #if !defined(AZTEC_C)            /* not tested very much */
  1030.     if (cmd == NULL)
  1031.     {
  1032. # ifndef NO_ARP
  1033.     if (dos2)
  1034. # endif
  1035.         x = SystemTags(p_sh, SYS_UserShell, TRUE, TAG_DONE);
  1036. # ifndef NO_ARP
  1037.     else
  1038.         x = Execute(p_sh, raw_in, raw_out);
  1039. # endif
  1040.     }
  1041.     else
  1042.     {
  1043. # ifndef NO_ARP
  1044.     if (dos2)
  1045. # endif
  1046.         x = SystemTags((char *)cmd, SYS_UserShell, TRUE, TAG_DONE);
  1047. # ifndef NO_ARP
  1048.     else
  1049.         x = Execute((char *)cmd, 0L, raw_out);
  1050. # endif
  1051.     }
  1052. # ifdef NO_ARP
  1053.     if (x < 0)
  1054. # else
  1055.     if ((dos2 && x < 0) || (!dos2 && !x))
  1056. # endif
  1057.     {
  1058.     MSG_PUTS("Cannot execute ");
  1059.     if (cmd == NULL)
  1060.     {
  1061.         MSG_PUTS("shell ");
  1062.         msg_outtrans(p_sh);
  1063.     }
  1064.     else
  1065.         msg_outtrans(cmd);
  1066.     msg_putchar('\n');
  1067.     retval = FAIL;
  1068.     }
  1069. # ifdef NO_ARP
  1070.     else if (x)
  1071. # else
  1072.     else if (!dos2 || x)
  1073. # endif
  1074.     {
  1075.     if (x = IoErr())
  1076.     {
  1077.         if (!expand_interactively)
  1078.         {
  1079.         msg_putchar('\n');
  1080.         msg_outnum((long)x);
  1081.         MSG_PUTS(" returned\n");
  1082.         }
  1083.         retval = FAIL;
  1084.     }
  1085.     }
  1086. #else    /* else part is for AZTEC_C */
  1087.     if (p_st >= 4 || (p_st >= 2 && options != SHELL_FILTER))
  1088.     use_execute = 1;
  1089.     else
  1090.     use_execute = 0;
  1091.     if (!use_execute)
  1092.     {
  1093.     /*
  1094.      * separate shell name from argument
  1095.      */
  1096.     shellcmd = vim_strsave(p_sh);
  1097.     if (shellcmd == NULL)        /* out of memory, use Execute */
  1098.         use_execute = 1;
  1099.     else
  1100.     {
  1101.         shellarg = skiptowhite(shellcmd);    /* find start of arguments */
  1102.         if (*shellarg != NUL)
  1103.         {
  1104.         *shellarg++ = NUL;
  1105.         shellarg = skipwhite(shellarg);
  1106.         }
  1107.     }
  1108.     }
  1109.     if (cmd == NULL)
  1110.     {
  1111.     if (use_execute)
  1112.     {
  1113. # ifndef NO_ARP
  1114.         if (dos2)
  1115. # endif
  1116.         x = SystemTags((UBYTE *)p_sh, SYS_UserShell, TRUE, TAG_DONE);
  1117. # ifndef NO_ARP
  1118.         else
  1119.         x = !Execute((UBYTE *)p_sh, raw_in, raw_out);
  1120. # endif
  1121.     }
  1122.     else
  1123.         x = fexecl((char *)shellcmd, (char *)shellcmd, (char *)shellarg, NULL);
  1124.     }
  1125.     else if (use_execute)
  1126.     {
  1127. # ifndef NO_ARP
  1128.     if (dos2)
  1129. # endif
  1130.         x = SystemTags((UBYTE *)cmd, SYS_UserShell, TRUE, TAG_DONE);
  1131. # ifndef NO_ARP
  1132.     else
  1133.         x = !Execute((UBYTE *)cmd, 0L, raw_out);
  1134. # endif
  1135.     }
  1136.     else if (p_st & 1)
  1137.     x = fexecl((char *)shellcmd, (char *)shellcmd, (char *)shellarg,
  1138.                                (char *)cmd, NULL);
  1139.     else
  1140.     x = fexecl((char *)shellcmd, (char *)shellcmd, (char *)shellarg,
  1141.                        (char *)p_shcf, (char *)cmd, NULL);
  1142. # ifdef NO_ARP
  1143.     if (x < 0)
  1144. # else
  1145.     if ((dos2 && x < 0) || (!dos2 && x))
  1146. # endif
  1147.     {
  1148.     MSG_PUTS("Cannot execute ");
  1149.     if (use_execute)
  1150.     {
  1151.         if (cmd == NULL)
  1152.         msg_outtrans(p_sh);
  1153.         else
  1154.         msg_outtrans(cmd);
  1155.     }
  1156.     else
  1157.     {
  1158.         MSG_PUTS("shell ");
  1159.         msg_outtrans(shellcmd);
  1160.     }
  1161.     msg_putchar('\n');
  1162.     retval = FAIL;
  1163.     }
  1164.     else
  1165.     {
  1166.     if (use_execute)
  1167.     {
  1168. # ifdef NO_ARP
  1169.         if (x)
  1170. # else
  1171.         if (!dos2 || x)
  1172. # endif
  1173.         x = IoErr();
  1174.     }
  1175.     else
  1176.         x = wait();
  1177.     if (x)
  1178.     {
  1179.         if (!expand_interactively)
  1180.         {
  1181.         msg_putchar('\n');
  1182.         msg_outnum((long)x);
  1183.         MSG_PUTS(" returned\n");
  1184.         }
  1185.         retval = FAIL;
  1186.     }
  1187.     }
  1188.     vim_free(shellcmd);
  1189. #endif    /* AZTEC_C */
  1190.  
  1191.     if (mydir = CurrentDir(mydir))    /* make sure we stay in the same directory */
  1192.     UnLock(mydir);
  1193.     settmode(TMODE_RAW);        /* set to raw mode */
  1194.     resettitle();
  1195.     if (term_console)
  1196.     win_resize_on();        /* window resize events activated */
  1197.     return retval;
  1198. }
  1199.  
  1200. /*
  1201.  * check for an "interrupt signal"
  1202.  * We only react to a CTRL-C, but also clear the other break signals to avoid
  1203.  * trouble with lattice-c programs.
  1204.  */
  1205.     void
  1206. mch_breakcheck()
  1207. {
  1208.    if (SetSignal(0L, (long)(SIGBREAKF_CTRL_C|SIGBREAKF_CTRL_D|SIGBREAKF_CTRL_E|SIGBREAKF_CTRL_F)) & SIGBREAKF_CTRL_C)
  1209.     got_int = TRUE;
  1210. }
  1211.  
  1212. /* this routine causes manx to use this Chk_Abort() rather than it's own */
  1213. /* otherwise it resets our ^C when doing any I/O (even when Enable_Abort */
  1214. /* is zero).  Since we want to check for our own ^C's             */
  1215.  
  1216. #ifdef _DCC
  1217. #define Chk_Abort chkabort
  1218. #endif
  1219.  
  1220. #ifdef LATTICE
  1221. void __regargs __chkabort(void);
  1222.  
  1223. void __regargs __chkabort(void)
  1224. {}
  1225.  
  1226. #else
  1227.     long
  1228. Chk_Abort(void)
  1229. {
  1230.     return(0L);
  1231. }
  1232. #endif
  1233.  
  1234. /*
  1235.  * mch_expandpath() - this code does wild-card pattern matching using the arp
  1236.  *              routines.
  1237.  *
  1238.  * Returns the number of matches found.
  1239.  *
  1240.  * This is based on WildDemo2.c (found in arp1.1 distribution).
  1241.  * That code's copyright follows:
  1242.  *    Copyright (c) 1987, Scott Ballantyne
  1243.  *    Use and abuse as you please.
  1244.  */
  1245.  
  1246. #define ANCHOR_BUF_SIZE (512)
  1247. #define ANCHOR_SIZE (sizeof(struct AnchorPath) + ANCHOR_BUF_SIZE)
  1248.  
  1249.     int
  1250. mch_expandpath(gap, pat, flags)
  1251.     struct growarray    *gap;
  1252.     char_u        *pat;
  1253.     int            flags;
  1254. {
  1255.     struct AnchorPath        *Anchor;
  1256.     LONG            Result;
  1257.     char_u            *starbuf, *sp, *dp;
  1258.     int                start_len;
  1259.     int                matches;
  1260.  
  1261.     start_len = gap->ga_len;
  1262.  
  1263.     /* Get our AnchorBase */
  1264.     Anchor = (struct AnchorPath *)alloc_clear((unsigned)ANCHOR_SIZE);
  1265.     if (Anchor == NULL)
  1266.     {
  1267.     EMSG("Out of memory");
  1268.     return 0;
  1269.     }
  1270.  
  1271.     Anchor->ap_Strlen = ANCHOR_BUF_SIZE;  /* ap_Length not supported anymore */
  1272. #ifdef APF_DODOT
  1273.     Anchor->ap_Flags = APF_DODOT | APF_DOWILD;    /* allow '.' for current dir */
  1274. #else
  1275.     Anchor->ap_Flags = APF_DoDot | APF_DoWild;    /* allow '.' for current dir */
  1276. #endif
  1277.  
  1278. #ifndef NO_ARP
  1279.     if (dos2)
  1280.     {
  1281. #endif
  1282.     /* hack to replace '*' by '#?' */
  1283.     starbuf = alloc((unsigned)(2 * STRLEN(pat) + 1));
  1284.     if (starbuf == NULL)
  1285.         goto Return;
  1286.     for (sp = pat, dp = starbuf; *sp; ++sp)
  1287.     {
  1288.         if (*sp == '*')
  1289.         {
  1290.         *dp++ = '#';
  1291.         *dp++ = '?';
  1292.         }
  1293.         else
  1294.         *dp++ = *sp;
  1295.     }
  1296.     *dp = NUL;
  1297.     Result = MatchFirst((UBYTE *)starbuf, Anchor);
  1298.     vim_free(starbuf);
  1299. #ifndef NO_ARP
  1300.     }
  1301.     else
  1302.     Result = FindFirst((char *)pat, Anchor);
  1303. #endif
  1304.  
  1305.     /*
  1306.      * Loop to get all matches.
  1307.      */
  1308.     while (Result == 0)
  1309.     {
  1310.     addfile(gap, (char_u *)Anchor->ap_Buf, flags);
  1311. #ifndef NO_ARP
  1312.     if (dos2)
  1313. #endif
  1314.         Result = MatchNext(Anchor);
  1315. #ifndef NO_ARP
  1316.     else
  1317.         Result = FindNext(Anchor);
  1318. #endif
  1319.     }
  1320.     matches = gap->ga_len - start_len;
  1321.  
  1322.     if (Result == ERROR_BUFFER_OVERFLOW)
  1323.     EMSG("ANCHOR_BUF_SIZE too small.");
  1324.     else if (matches == 0 && Result != ERROR_OBJECT_NOT_FOUND
  1325.               && Result != ERROR_NO_MORE_ENTRIES)
  1326.     EMSG("I/O ERROR");
  1327.  
  1328.     /*
  1329.      * Sort the files for this pattern.
  1330.      */
  1331.     if (matches)
  1332.     qsort((void *)(((char_u **)gap->ga_data) + start_len),
  1333.                   (size_t)matches, sizeof(char_u *), sortcmp);
  1334.  
  1335.     /* Free the wildcard stuff */
  1336. #ifndef NO_ARP
  1337.     if (dos2)
  1338. #endif
  1339.     MatchEnd(Anchor);
  1340. #ifndef NO_ARP
  1341.     else
  1342.     FreeAnchorChain(Anchor);
  1343. #endif
  1344.  
  1345. Return:
  1346.     vim_free(Anchor);
  1347.  
  1348.     return matches;
  1349. }
  1350.  
  1351.     static int
  1352. sortcmp(a, b)
  1353.     char **a, **b;
  1354. {
  1355.     return stricmp(*a, *b);
  1356. }
  1357.  
  1358.     int
  1359. mch_has_wildcard(p)
  1360.     char_u *p;
  1361. {
  1362.     return (vim_strpbrk(p, (char_u *)"*?[(~#$") != NULL);
  1363. }
  1364.  
  1365. /*
  1366.  * With AmigaDOS 2.0 support for reading local environment variables
  1367.  *
  1368.  * Two buffers are allocated:
  1369.  * - A big one to do the expansion into.  It is freed before returning.
  1370.  * - A small one to hold the return value.  It is kept until the next call.
  1371.  */
  1372.     char_u *
  1373. vim_getenv(var)
  1374.     char_u *var;
  1375. {
  1376.     int            len;
  1377.     UBYTE        *buf;        /* buffer to expand in */
  1378.     char_u        *retval;        /* return value */
  1379.     static char_u   *alloced = NULL;    /* allocated memory */
  1380.  
  1381. #ifndef NO_ARP
  1382.     if (!dos2)
  1383.     retval = (char_u *)getenv((char *)var);
  1384.     else
  1385. #endif
  1386.     {
  1387.     vim_free(alloced);
  1388.     alloced = NULL;
  1389.     retval = NULL;
  1390.  
  1391.     buf = alloc(IOSIZE);
  1392.     if (buf == NULL)
  1393.         return NULL;
  1394.  
  1395.     len = GetVar((UBYTE *)var, buf, (long)(IOSIZE - 1), (long)0);
  1396.     if (len >= 0)
  1397.     {
  1398.         retval = vim_strsave((char_u *)buf);
  1399.         alloced = retval;
  1400.     }
  1401.  
  1402.     vim_free(buf);
  1403.     }
  1404.  
  1405.     /* if $VIM is not defined, use "vim:" instead */
  1406.     if (retval == NULL && STRCMP(var, "VIM") == 0)
  1407.     retval = (char_u *)"vim:";
  1408.  
  1409.     return retval;
  1410. }
  1411.  
  1412. /*
  1413.  * Amiga version of setenv() with AmigaDOS 2.0 support.
  1414.  */
  1415.     int
  1416. vim_setenv(var, value)
  1417.     char *var;
  1418.     char *value;
  1419. {
  1420. #ifndef NO_ARP
  1421.     if (!dos2)
  1422.     return setenv(var, value);
  1423. #endif
  1424.  
  1425.     if (SetVar((UBYTE *)var, (UBYTE *)value, (LONG)-1, (ULONG)GVF_LOCAL_ONLY))
  1426.     return 0;   /* success */
  1427.     return -1;        /* failure */
  1428. }
  1429.